package com.af.soldiers.timer;

import com.af.soldiers.config.Monitor;
import com.af.soldiers.entity.InstructionsFragment;
import com.af.soldiers.job.RunSql;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;


@Component
public class Fragment {

    @Autowired
    private RunSql runSql;

    @Autowired
    private Monitor monitor;

    HttpComponentsClientHttpRequestFactory httpRequestFactory;

    private static final Logger logger = LoggerFactory.getLogger(Fragment.class);

    public Fragment(){
        httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(1000 * 10);
        httpRequestFactory.setConnectTimeout(1000 * 10);
        httpRequestFactory.setReadTimeout(1000 * 10);
    }

    @Async
    @Scheduled(cron = "0 30 6,9,12,15,18,21 * * ? ")
    public void pushFragmentInfo(){
        try {
            // 获取当前链接库名
            String queryDBName = "select DB_name() as dbName";

            String queryFragment = "SELECT\n" +
                    "T.Name AS tableName,\n" +
                    "I.name AS indexName,\n" +
                    "I.type AS indexType,\n" +
                    "D.avg_fragmentation_in_percent AS indexFragment,\n" +
                    "page_count indexPage,\n" +
                    "B.rows as tableRows\n" +
                    "FROM\n" +
                    "sys.dm_db_index_physical_stats ( DB_id( ), NULL, NULL, NULL, NULL ) AS D\n" +
                    "INNER JOIN sys.indexes AS I WITH ( NOLOCK ) ON D.index_id= I.index_id\n" +
                    "AND D.object_id = I.object_id\n" +
                    "INNER JOIN sys.tables AS T WITH ( NOLOCK ) ON T.object_id = D.object_id\n" +
                    "INNER JOIN sysindexes AS B WITH ( NOLOCK ) ON T.object_id = B.id AND T.type = 'u' AND (B.indid IN (0, 1))\n" +
                    "WHERE\n" +
                    "I.type> 0\n" +
                    "AND T.is_ms_shipped= 0\n" +
                    "AND D.avg_fragmentation_in_percent>= 20\n" +
                    "AND page_count >= 1000\n" +
                    "ORDER BY\n" +
                    "D.avg_fragmentation_in_percent DESC";


            ResponseEntity<String> forEntity = new RestTemplate(httpRequestFactory)
                    .postForEntity(monitor.getBackUrl() + "fragment/save/" + monitor.getId() + "/"
                            + runSql.select(queryDBName).getJSONObject(0).getString("dbName"),
            new JSONObject(){{
                put("fragment",runSql.select(queryFragment));
            }}, String.class);

            logger.info("索引碎片数据推送完毕 响应-》" + forEntity.getStatusCodeValue());
        } catch (Exception throwables) {
            logger.error("查询索引处 执行SQL异常！" , throwables);
        }
    }

    @Async
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void gushFragmentTask(){
        try {
            // 获取当前链接库名
            String queryDBName = "select DB_name() as dbName";
            String dbName = runSql.select(queryDBName).getJSONObject(0).getString("dbName");
            ResponseEntity<String> forEntity = new RestTemplate(httpRequestFactory)
                    .getForEntity(monitor.getBackUrl() + "fragment/get/" + monitor.getId() + "/" + dbName ,String.class);
            JSONArray data = JSON.parseObject(forEntity.getBody()).getJSONArray("data");
            if (data.size() > 0){
                for (int i = 0; i < data.size(); i++) {
                    InstructionsFragment instructionsFragment = JSONObject.parseObject(data.getJSONObject(i).toJSONString(), InstructionsFragment.class);
                    try {
                        String sql = "ALTER INDEX [" + instructionsFragment.getIndexName() + "] ON [" + instructionsFragment.getTableName() + "] REBUILD;";
                        long start = System.currentTimeMillis();
                        runSql.execute(sql);
                        instructionsFragment.setTaskState(2).setTaskRemarks("执行成功，耗时" + (System.currentTimeMillis() - start) + "ms");
                    }catch (Exception e){
                        instructionsFragment.setTaskState(3).setTaskRemarks(e.getMessage());
                        logger.error("执行索引重建出错：", e);
                    }finally {
                        new RestTemplate(httpRequestFactory)
                                .postForEntity(monitor.getBackUrl() + "fragment/save/instructions",instructionsFragment,String.class);
                    }
                }
                pushFragmentInfo();
            }
            logger.debug("index clean Over");
        } catch (Exception throwables) {
            logger.error("重建索引处 执行SQL异常！" ,throwables);
        }
    }

}
